package editorsvg.gui.generico;

import java.util.Arrays;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;

/**
 * Panel para la edici�n de una lista de valores
 * 
 * @author  Jorge Berjano
 */
public class PanelListaValores extends javax.swing.JPanel {

    private DefaultListModel modelo;
    private Parseador parseador;
    private Actualizable observadorActualizacion;

    /** Constructor */
    public PanelListaValores() {
        initComponents();

        modelo = new DefaultListModel();
        listaValores.setModel(modelo);
        setParseador(new ParseadorString());
    }

    public String getTextoValor() {
        return etiquetaValor.getText();
    }

    public void setTextoValor(String textoValor) {
        etiquetaValor.setText(textoValor);
    }

    public String getTextoLista() {
        return etiquetaLista.getText();
    }

    public void setTextoLista(String textoLista) {
        etiquetaLista.setText(textoLista);
    }

    public boolean tieneValores() {
        return modelo.size() > 0;
    }

    /**
     * Contrato que cumplen las clases parseadoras.
     * Las clases parseadoras transforman el texto editado en el objeto adecuado para cada caso.
     */
    public interface Parseador {

        Object parsear(String valorTexto);
    }

    public class ParseadorString implements Parseador {

        public Object parsear(String valorTexto) {
            if (valorTexto != null && valorTexto.length() == 0) {
                return null;            
            } else {
                return valorTexto;
            }
        }
    }

    public class ParseadorInteger implements Parseador {

        public Object parsear(String valorTexto) {
            try {
                return Integer.parseInt(valorTexto);
            } catch (Exception ex) {
                return null;
            }
        }
    }

    public class ParseadorDouble implements Parseador {

        public Object parsear(String valorTexto) {
            try {
                return Double.parseDouble(valorTexto);
            } catch (Exception ex) {
                return null;
            }
        }
    }

    public void asignarLista(List lista) {
        modelo.removeAllElements();

        for (Object valor : lista) {
            modelo.addElement(valor);
        }
    }

    public List recuperarLista() {
        return Arrays.asList(modelo.toArray());
    }
    
    public void asignarValoresPropuestos(List lista) {
        comboValor.setModel(new ModeloListaCombo(lista));
    }

    public Parseador getParseador() {
        return parseador;
    }

    public void setParseador(Parseador parseador) {
        this.parseador = parseador;
    }
    
    public void setObservadorActualizacion(Actualizable observadorActualizacion) {
        this.observadorActualizacion = observadorActualizacion;
    }

    private void añadirValor() {
        Object seleccionado = comboValor.getSelectedItem();
        if (seleccionado == null)
            return;
        
        Object valor = parseador.parsear(seleccionado.toString());
        if (valor == null) {
            JOptionPane.showMessageDialog(this, "No se puede a�adir el valor " +
                    seleccionado.toString(), "Aviso", JOptionPane.WARNING_MESSAGE);
            return;
        }

        modelo.addElement(valor);
        listaValores.setSelectedIndex(modelo.size() - 1);
        comboValor.requestFocus();
//        comboValor.setSelectionStart(0);
//        comboValor.setSelectionEnd(campoValor.getText().length());
        observadorActualizacion.actualizar();
    }

    private void editarValor() {
        int indice = listaValores.getSelectedIndex();
        if (indice < 0) {
            return;
        }
        String texto = comboValor.getSelectedItem().toString();
        
        Object valor = parseador.parsear(texto);
        if (valor != null) {
            modelo.setElementAt(valor, indice);
            observadorActualizacion.actualizar();
        } else {
            JOptionPane.showMessageDialog(this, "No se puede asignar el valor " +
                    texto, "Aviso", JOptionPane.WARNING_MESSAGE);
        }
    }

    private void eliminarValor() {
        int indice = listaValores.getSelectedIndex();
        if (indice < 0) {
            return;
        }

        modelo.remove(indice);        
        
        if (indice < modelo.size()) {
            listaValores.setSelectedIndex(indice);
        } else if (indice > 0) {
            listaValores.setSelectedIndex(indice - 1);
        } else {
            comboValor.setSelectedItem(null);
        }
        
        observadorActualizacion.actualizar();
    }

    private void seleccionarValor() {
        int indice = listaValores.getSelectedIndex();
        if (indice < 0) {
            return;
        }

        comboValor.setSelectedItem(modelo.get(indice));
    }

    private void subirValor() {
        int indice = listaValores.getSelectedIndex();
        if (indice <= 0) {
            return;
        }

        Object valor = modelo.get(indice);
        Object valorAnterior = modelo.get(indice - 1);
        modelo.set(indice, valorAnterior);
        modelo.set(indice - 1, valor);

        listaValores.setSelectedIndex(indice - 1);
        
        observadorActualizacion.actualizar();
    }

    private void bajarValor() {
        int indice = listaValores.getSelectedIndex();
        if (indice < 0 || indice == modelo.size() - 1) {
            return;
        }

        Object valor = modelo.get(indice);
        Object valorPosterior = modelo.get(indice + 1);
        modelo.set(indice, valorPosterior);
        modelo.set(indice + 1, valor);

        listaValores.setSelectedIndex(indice + 1);
        
        observadorActualizacion.actualizar();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        panelValores = new javax.swing.JPanel();
        etiquetaValor = new javax.swing.JLabel();
        etiquetaLista = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        listaValores = new javax.swing.JList();
        comboValor = new javax.swing.JComboBox();
        panelBotones = new javax.swing.JPanel();
        botonEliminar = new javax.swing.JButton();
        botonBajar = new javax.swing.JButton();
        botonSubir = new javax.swing.JButton();
        botonEditar = new javax.swing.JButton();
        botonAgregar = new javax.swing.JButton();

        setLayout(new java.awt.BorderLayout());

        etiquetaValor.setText("Valor:");

        etiquetaLista.setText("Lista de valores");

        listaValores.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        listaValores.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                listaValoresValueChanged(evt);
            }
        });
        jScrollPane2.setViewportView(listaValores);

        comboValor.setEditable(true);

        org.jdesktop.layout.GroupLayout panelValoresLayout = new org.jdesktop.layout.GroupLayout(panelValores);
        panelValores.setLayout(panelValoresLayout);
        panelValoresLayout.setHorizontalGroup(
            panelValoresLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(panelValoresLayout.createSequentialGroup()
                .addContainerGap()
                .add(panelValoresLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jScrollPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 281, Short.MAX_VALUE)
                    .add(panelValoresLayout.createSequentialGroup()
                        .add(etiquetaValor)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(comboValor, 0, 249, Short.MAX_VALUE))
                    .add(etiquetaLista))
                .addContainerGap())
        );
        panelValoresLayout.setVerticalGroup(
            panelValoresLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(panelValoresLayout.createSequentialGroup()
                .addContainerGap()
                .add(panelValoresLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(etiquetaValor)
                    .add(comboValor, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(etiquetaLista)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jScrollPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 230, Short.MAX_VALUE)
                .addContainerGap())
        );

        add(panelValores, java.awt.BorderLayout.CENTER);

        botonEliminar.setText("Eliminar");
        botonEliminar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonEliminarActionPerformed(evt);
            }
        });

        botonBajar.setText("Bajar");
        botonBajar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonBajarActionPerformed(evt);
            }
        });

        botonSubir.setText("Subir");
        botonSubir.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonSubirActionPerformed(evt);
            }
        });

        botonEditar.setText("Editar");
        botonEditar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonEditarActionPerformed(evt);
            }
        });

        botonAgregar.setText("Añadir");
        botonAgregar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonAgregarActionPerformed(evt);
            }
        });

        org.jdesktop.layout.GroupLayout panelBotonesLayout = new org.jdesktop.layout.GroupLayout(panelBotones);
        panelBotones.setLayout(panelBotonesLayout);
        panelBotonesLayout.setHorizontalGroup(
            panelBotonesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(panelBotonesLayout.createSequentialGroup()
                .add(panelBotonesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(botonEliminar, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 75, Short.MAX_VALUE)
                    .add(botonSubir, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 75, Short.MAX_VALUE)
                    .add(botonBajar, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 75, Short.MAX_VALUE)
                    .add(botonAgregar, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 75, Short.MAX_VALUE)
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, botonEditar, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 75, Short.MAX_VALUE))
                .addContainerGap())
        );
        panelBotonesLayout.setVerticalGroup(
            panelBotonesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(panelBotonesLayout.createSequentialGroup()
                .addContainerGap()
                .add(botonAgregar)
                .add(4, 4, 4)
                .add(botonEditar)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(botonEliminar)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 150, Short.MAX_VALUE)
                .add(botonSubir)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(botonBajar)
                .add(8, 8, 8))
        );

        add(panelBotones, java.awt.BorderLayout.EAST);
    }// </editor-fold>//GEN-END:initComponents
    private void botonBajarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonBajarActionPerformed
        bajarValor();
    }//GEN-LAST:event_botonBajarActionPerformed

    private void botonSubirActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonSubirActionPerformed
        subirValor();
    }//GEN-LAST:event_botonSubirActionPerformed

    private void listaValoresValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_listaValoresValueChanged
        seleccionarValor();
    }//GEN-LAST:event_listaValoresValueChanged

    private void botonEliminarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonEliminarActionPerformed
        eliminarValor();
    }//GEN-LAST:event_botonEliminarActionPerformed

    private void botonEditarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonEditarActionPerformed
        editarValor();
    }//GEN-LAST:event_botonEditarActionPerformed

private void botonAgregarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonAgregarActionPerformed
    añadirValor();
}//GEN-LAST:event_botonAgregarActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton botonAgregar;
    private javax.swing.JButton botonBajar;
    private javax.swing.JButton botonEditar;
    private javax.swing.JButton botonEliminar;
    private javax.swing.JButton botonSubir;
    private javax.swing.JComboBox comboValor;
    private javax.swing.JLabel etiquetaLista;
    private javax.swing.JLabel etiquetaValor;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JList listaValores;
    private javax.swing.JPanel panelBotones;
    private javax.swing.JPanel panelValores;
    // End of variables declaration//GEN-END:variables
}
